home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / fly / fly.c < prev    next >
C/C++ Source or Header  |  1996-01-22  |  29KB  |  1,091 lines

  1. /*******************************************************************************
  2. **  fly:  On-the-fly GIF creation utility
  3. **  Martin Gleeson, ITS, gleeson@unimelb.edu.au
  4. **  Copyright (c), The University of Melbourne, 1994,1995,1996
  5. **  Last Update: 23 Jan 1996
  6. **
  7. **  Uses the gd library by Thomas Boutell, boutell@netcom.com
  8. **  gd: Copyright 1994, Quest Protein Database Centre, Cold Spring Harbour Labs
  9. **
  10. **  Contributions from:
  11. **  John Bowe <bowe@osf.org>
  12. **     addition of better argument parsing
  13. **  Claus Hofmann <claush@ipfr.bau-verm.uni-karlsruhe.de>
  14. **     addition of 'transparent' directive.
  15. **     addtion of code to check if colour already allocated
  16. **     addition of feature to copy whole image if all coords are -1
  17. **
  18. *******************************************************************************/
  19.  
  20. char *version = "1.3";
  21. char *usage = "Usage : fly [-h] [-q] [-i inputfile] [-o outputfile.gif]";
  22.  
  23. char *help = "Quick Reference to Directives: \n\nline  x1,y1,x2,y2,R,G,B             dline        x1,y1,x2,y2,R,G,B \nrect  x1,y1,x2,y2,R,G,B             frect        x1,y1,x2,y2,R,G,B \npoly  R,G,B,x1,y1...,xn,yn          fpoly        R,G,B,x1,y1...,xn,yn \nfill  x,y,R,G,B                     filltoborder x,y,R1,G1,B1,R2,B2,G2 \narc   x1,y1,w,h,start,finish,R,G,B  circle       x,y,r,R,G,B \n\string   R,G,B,x,y,<size>,<string> \nstringup R,G,B,x,y,<size>,<string> \n(size = tiny, small, medium, large or giant) \n\ncopy         x,y,x1,y1,x2,y2,filename.gif \ncopyresized  x1,y1,x2,y2,dx1,dy1,dx2,dy2,filename.gif \n\nsetpixel    x,y,R,G,B \ntransparent R,G,B \ninterlace \n\nsetbrush    filename.gif                         killbrush \nsettile     filename.gif                         killtile \nsetstyle    R1,G1,B1,R2,G2,B2,...,Rn,Bn,Gn       killstyle \n\nsizex \nsizey \n";
  24.  
  25. /******************************************************************************/
  26.  
  27. #include "gd.h"
  28. #include "gdfonts.h"
  29. #include "gdfontl.h"
  30. #include "gdfontmb.h"
  31. #include "gdfontt.h"
  32. #include "gdfontg.h"
  33. #include "fly.h"
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <errno.h>
  37. #include <string.h>
  38.  
  39. /******************************************************************************
  40. **  Internal Functions
  41. ******************************************************************************/
  42.  
  43. int         process_args(int argc, char *argv[]);
  44. int         get_token(FILE *infile);
  45. int         get_number(FILE *infile);
  46. char       *get_string(FILE *infile);
  47. void        sync_input(FILE *infile);
  48. int         get_colour(FILE *infile, gdImagePtr img);
  49. void        copy_to_gif(FILE *infile, gdImagePtr img, int resize);
  50. gdImagePtr  get_image(int type, int argc, char *argv[]);
  51. void       *my_newmem(size_t size);
  52.  
  53. /******************************************************************************
  54. **  Global Variables 
  55. ******************************************************************************/
  56.  
  57. int   finished = FALSE,
  58.           done = FALSE,
  59.          quiet = FALSE,
  60.    end_of_line = FALSE;
  61.  
  62. char     *input_file,
  63.          *output_file;
  64.  
  65. FILE     *outfile;
  66. FILE     *infile;
  67. FILE     *brushfile;
  68. FILE     *tilefile;
  69.  
  70. /******************************************************************************
  71. ** Main Program
  72. ******************************************************************************/
  73.  
  74. int main(int argc, char *argv[]){
  75.     int colour, colour2, type;
  76.     int status, size;
  77.     int brush_on = 0, tile_on = 0, style_on = 0;
  78.     int num_entries, up = 0;
  79.     int i, n, c, x, y;
  80.     int arg[4096], style[1024];
  81.     char *s;
  82.     gdPoint points[2048];
  83.     gdImagePtr img, brush, tile;
  84.  
  85.     status = process_args(argc, argv);
  86.     if (status == FALSE) exit(0);
  87.  
  88.     type = get_token(infile);
  89.     while( type == COMMENT )
  90.     {
  91.         sync_input(infile);
  92.         type = get_token(infile);
  93.     }
  94.     if( type != NEW     && type != EXISTING)
  95.     {
  96.         fprintf(stderr,"Error: Must use 'new' or 'existing' directive first in input.\n");
  97.         exit(1);
  98.     }
  99.     img=get_image(type, argc, argv);
  100.  
  101.     /* while more lines to process */
  102.     do{
  103.         type = get_token(infile);
  104.         switch(type){
  105.  
  106.         case LINE:      /*      gdImageLine()           */
  107.             for(i=1;i<=4;i++)
  108.             {
  109.                 arg[i]=get_number(infile);
  110.             }
  111.             if (!quiet) fprintf(stderr,"## Line ## drawn from %d,%d to %d,%d. (",
  112.                 arg[1],arg[2],arg[3],arg[4]);
  113.             if( brush_on )
  114.             {
  115.                 sync_input(infile);
  116.                 gdImageLine(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
  117.                 if (!quiet) fprintf(stderr,"colour = current brush");
  118.             }
  119.             else if ( style_on )
  120.             {
  121.                 sync_input(infile);
  122.                 gdImageLine(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
  123.                 if (!quiet) fprintf(stderr,"colour = current style");
  124.             }
  125.             else
  126.             {
  127.                 colour=get_colour(infile,img);
  128.                 gdImageLine(img,arg[1],arg[2],arg[3],arg[4],colour);
  129.             }
  130.             if (!quiet) fprintf(stderr,")\n");
  131.             break;
  132.  
  133.  
  134.         case DLINE:     /*      gdImageDashedLine()     */
  135.             for(i=1;i<=4;i++){
  136.                 arg[i]=get_number(infile);
  137.             }
  138.             if (!quiet)
  139.                 fprintf(stderr,"## Dashed Line ## drawn from %d,%d to %d,%d. (",
  140.                 arg[1],arg[2],arg[3],arg[4]);
  141.             if( brush_on ){
  142.                 sync_input(infile);
  143.                 gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
  144.                 if (!quiet) fprintf(stderr,"colour = current brush");
  145.             } else if ( style_on ) {
  146.                 sync_input(infile);
  147.                 gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
  148.                 if (!quiet) fprintf(stderr,"colour = current style");
  149.             } else{
  150.                 colour=get_colour(infile,img);
  151.                 gdImageDashedLine(img,arg[1],arg[2],arg[3],arg[4],colour);
  152.             }
  153.             if (!quiet) fprintf(stderr,")\n");
  154.             break;
  155.  
  156.         case RECT:      /*      gdImageRectangle()      */
  157.             for(i=1;i<=4;i++){
  158.                 arg[i]=get_number(infile);
  159.             }
  160.             if (!quiet) fprintf(stderr,"## Rectangle ## drawn from %d,%d to %d,%d. (",
  161.                 arg[1],arg[2],arg[3],arg[4]);
  162.             if( brush_on ){
  163.                 sync_input(infile);
  164.                 gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdBrushed);
  165.                 if (!quiet) fprintf(stderr,"colour = current brush");
  166.             } else if ( style_on ) {
  167.                 sync_input(infile);
  168.                 gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],gdStyled);
  169.                 if (!quiet) fprintf(stderr,"colour = current style");
  170.             } else{
  171.                 colour=get_colour(infile,img);
  172.                 gdImageRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
  173.             }
  174.             if (!quiet) fprintf(stderr,")\n");
  175.             break;
  176.  
  177.  
  178.         case FRECT:     /*      gdImageFilledRectangle() */
  179.             for(i=1;i<=4;i++){
  180.                 arg[i]=get_number(infile);
  181.             }
  182.             if (!quiet)
  183.                 fprintf(stderr,"## Filled Rectangle ## drawn from %d,%d to %d,%d. (",
  184.                 arg[1],arg[2],arg[3],arg[4]);
  185.             if( tile_on ){
  186.                 sync_input(infile);
  187.                 gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],gdTiled);
  188.                 if (!quiet) fprintf(stderr,"colour = current tile");
  189.             } else{
  190.                 colour=get_colour(infile,img);
  191.                 gdImageFilledRectangle(img,arg[1],arg[2],arg[3],arg[4],colour);
  192.             }
  193.             if (!quiet) fprintf(stderr,")\n");
  194.             break;
  195.  
  196.         case POLY:      /* create polygon with gdImageLine() calls */
  197.             done = FALSE; i=0;
  198.  
  199.             if (!quiet) fprintf(stderr,"## Polygon ## (");
  200.             colour=get_colour(infile,img);
  201.             if (!quiet) fprintf(stderr,") ");
  202.  
  203.             arg[i++] = get_number(infile); /* get first point */
  204.             arg[i++] = get_number(infile);
  205.  
  206.             while( ! done ){     /* get next point until EOL*/
  207.                 for(c=0; c<=1 ;c++){
  208.                     arg[i++]=get_number(infile);
  209.                 }
  210.                 if (!quiet) fprintf(stderr,"%d,%d to %d,%d; ",
  211.                     arg[i-4],arg[i-3],arg[i-2],arg[i -1]);
  212.             }
  213.  
  214.             num_entries = i / 2;  i=0;
  215.             for(n=0; n<num_entries; n++)
  216.             {
  217.                 points[n].x = arg[i++];
  218.                 points[n].y = arg[i++];
  219.             }
  220.             if( brush_on ) {
  221.                 gdImagePolygon(img, points, num_entries, gdBrushed);
  222.             } else if ( style_on ) {
  223.                 gdImagePolygon(img, points, num_entries, gdStyled);
  224.             } else {
  225.                 gdImagePolygon(img, points, num_entries, colour);
  226.             }
  227.  
  228.             done = FALSE;
  229.             if (!quiet) fprintf(stderr,"\n");
  230.             break;
  231.  
  232.         case FPOLY:      /* create polygon with gdImageLine() calls */
  233.             done = FALSE; i=0;
  234.  
  235.             if (!quiet) fprintf(stderr,"## Filled Polygon ## (");
  236.             colour=get_colour(infile,img);
  237.             if (!quiet) fprintf(stderr,") ");
  238.  
  239.             arg[i++] = get_number(infile); /* get first point */
  240.             arg[i++] = get_number(infile);
  241.  
  242.             while( ! done ){     /* get next point until EOL*/
  243.                 for(c=0; c<=1 ;c++){
  244.                     arg[i++]=get_number(infile);
  245.                 }
  246.                 if (!quiet) fprintf(stderr,"%d,%d to %d,%d; ",
  247.                     arg[i-4],arg[i-3],arg[i-2],arg[i -1]);
  248.             }
  249.  
  250.             num_entries = i / 2;  i=0;
  251.             for(n=0; n<num_entries; n++)
  252.             {
  253.                 points[n].x = arg[i++];
  254.                 points[n].y = arg[i++];
  255.             }
  256.  
  257.             if( tile_on )
  258.             {
  259.                 gdImageFilledPolygon(img, points, num_entries, gdTiled);
  260.             }
  261.             else
  262.             {
  263.                 gdImageFilledPolygon(img, points, num_entries, colour);
  264.             }
  265.             done = FALSE;
  266.             if (!quiet) fprintf(stderr,"\n");
  267.             break;
  268.  
  269.         case ARC:       /*      gdImageArc()            */
  270.             for(i=1;i<7;i++){
  271.                 arg[i]=get_number(infile);
  272.             }
  273.             if (!quiet) {
  274.                 fprintf(stderr,"## Arc ## Centred at %d,%d, width %d, height %d,\n",
  275.                     arg[1],arg[2],arg[3],arg[4]);
  276.                 fprintf(stderr,"          starting at %d deg, ending at %d deg. (",
  277.                     arg[5],arg[6]);
  278.             }
  279.             if( brush_on ){
  280.             sync_input(infile);
  281.             gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],gdBrushed);
  282.             if(!quiet) fprintf(stderr,"colour = current brush");
  283.             } else if ( style_on ) {
  284.             sync_input(infile);
  285.             gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],gdStyled);
  286.             if(!quiet) fprintf(stderr,"colour = current style");
  287.             } else{
  288.             colour=get_colour(infile,img);
  289.             gdImageArc(img,arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],colour);
  290.             }
  291.             if (!quiet) fprintf(stderr,")\n");
  292.             break;
  293.  
  294.         case CIRCLE:
  295.             for(i=1;i<4;i++){
  296.                 arg[i]=get_number(infile);
  297.             }
  298.             if (!quiet) {
  299.                 fprintf(stderr,"## Circle ## Centred at %d,%d, radius %d (",
  300.                     arg[1],arg[2],arg[3]);
  301.             }
  302.             if( brush_on ){
  303.             sync_input(infile);
  304.             gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,gdBrushed);
  305.             if(!quiet) fprintf(stderr,"colour = current brush");
  306.             } else if ( style_on ) {
  307.             sync_input(infile);
  308.             gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,gdStyled);
  309.             if(!quiet) fprintf(stderr,"colour = current style");
  310.             } else{
  311.             colour=get_colour(infile,img);
  312.             gdImageArc(img,arg[1],arg[2],arg[3],arg[3],0,360,colour);
  313.             }
  314.             if (!quiet) fprintf(stderr,")\n");
  315.             break;
  316.  
  317.  
  318.         case SETPIXEL:      /*    gdImageSetPixel  */
  319.             for(i=1;i<=2;i++){
  320.                 arg[i]=get_number(infile);
  321.             }
  322.             if (!quiet) fprintf(stderr,"## Set Pixel ## at %d,%d to ",arg[1],arg[2]);
  323.             colour=get_colour(infile,img);
  324.             gdImageSetPixel(img,arg[1],arg[2],colour);
  325.             if (!quiet) fprintf(stderr,".\n");
  326.             break;
  327.  
  328.         case FILL:      /*      gdImageFill() */
  329.             for(i=1;i<=2;i++){
  330.                 arg[i]=get_number(infile);
  331.             }
  332.             if (!quiet) fprintf(stderr,"## Fill ## from %d,%d. (", arg[1],arg[2]);
  333.             if( tile_on ){
  334.                 sync_input(infile);
  335.                 gdImageFill(img,arg[1],arg[2],gdTiled);
  336.             } else {
  337.                 colour=get_colour(infile,img);
  338.                 gdImageFill(img,arg[1],arg[2],colour);
  339.             }
  340.             if (!quiet) fprintf(stderr,")\n");
  341.             break;
  342.  
  343.         case FILLTOBORDER:      /*    gdImageFillToBorder()    */
  344.             for(i=1;i<=2;i++){
  345.                 arg[i]=get_number(infile);
  346.             }
  347.             if (!quiet) fprintf(stderr,"## Fill ## from %d,%d. (", arg[1],arg[2]);
  348.             colour=get_colour(infile,img);
  349.             if (!quiet) fprintf(stderr,") to Border of ");
  350.             if( tile_on ){
  351.                 sync_input(infile);
  352.                 gdImageFillToBorder(img,arg[1],arg[2],colour,gdTiled);
  353.             } else {
  354.                 colour2=get_colour(infile,img);
  355.                 gdImageFillToBorder(img,arg[1],arg[2],colour,colour2);
  356.             }
  357.             if (!quiet) fprintf(stderr,".\n");
  358.             break;
  359.  
  360.         case STRINGUP:
  361.             up = TRUE;
  362.         case STRING:
  363.             if (!quiet && up) fprintf(stderr,"## String (Up) ## (");
  364.             if (!quiet && !up) fprintf(stderr,"## String ## (");
  365.             colour=get_colour(infile,img);
  366.             if (!quiet) fprintf(stderr,") at location ");
  367.             for(i=1;i<=2;i++){
  368.                 arg[i]=get_number(infile);
  369.             }
  370.             if (!quiet) fprintf(stderr," %d,%d, ",arg[1],arg[2]);
  371.             i=get_token(infile);
  372.             switch(i)
  373.             {
  374.             case TINY:
  375.                 s = get_string(infile);
  376.                 if (!quiet) fprintf(stderr,"[size: tiny] contents: %s\n",s);
  377.                 if( !up ) {
  378.                 gdImageString(img, gdFontTiny, arg[1],arg[2], s, colour);
  379.                 } else {
  380.                 gdImageStringUp(img, gdFontTiny, arg[1],arg[2], s, colour);
  381.                 }
  382.                 break;
  383.             case SMALL:
  384.                 s = get_string(infile);
  385.                 if (!quiet) fprintf(stderr,"[size: small] contents: %s\n",s);
  386.                 if( !up ) {
  387.                 gdImageString(img, gdFontSmall, arg[1],arg[2], s, colour);
  388.                 } else {
  389.                 gdImageStringUp(img, gdFontSmall, arg[1],arg[2], s, colour);
  390.                 }
  391.                 break;
  392.             case MEDIUM:
  393.                 s = get_string(infile);
  394.                 if (!quiet) fprintf(stderr,"[size: medium-bold] contents: %s\n",s);
  395.                 if( !up ) {
  396.                 gdImageString(img,gdFontMediumBold, arg[1],arg[2],s,colour);
  397.                 } else {
  398.                 gdImageStringUp(img,gdFontMediumBold,arg[1],arg[2],s,colour);
  399.                 }
  400.                 break;
  401.             case LARGE:
  402.                 s = get_string(infile);
  403.                 if (!quiet) fprintf(stderr,"[size: large] contents: %s\n",s);
  404.                 if( !up ) {
  405.                 gdImageString(img, gdFontLarge, arg[1],arg[2], s, colour);
  406.                 } else {
  407.                 gdImageStringUp(img, gdFontLarge, arg[1],arg[2], s, colour);
  408.                 }
  409.                 break;
  410.             case GIANT:
  411.                 s = get_string(infile);
  412.                 if (!quiet) fprintf(stderr,"[size: giant] contents: %s\n",s);
  413.                 if( !up ) {
  414.                 gdImageString(img, gdFontGiant, arg[1],arg[2], s, colour);
  415.                 } else {
  416.                 gdImageStringUp(img, gdFontGiant, arg[1],arg[2], s, colour);
  417.                 }
  418.                 break;
  419.             }
  420.             up = FALSE;
  421.             break;
  422.  
  423.         case SETBRUSH:
  424.             s = get_string(infile);
  425.             brushfile = fopen(s,"rb");
  426.             brush = gdImageCreateFromGif(brushfile);
  427.             gdImageSetBrush(img,brush);
  428.             brush_on = 1;
  429.             if (!quiet) fprintf(stderr,"## Brush Set ## to: %s\n",s);
  430.             break;
  431.  
  432.         case KILLBRUSH:
  433.             brush_on = 0;
  434.             if (!quiet) fprintf(stderr,"## Brush Killed ##\n");
  435.             break;
  436.  
  437.         case SETSTYLE:
  438.             i=0;
  439.             end_of_line = FALSE;
  440.             if (!quiet) fprintf(stderr,"## Style Set ## Colours: (");
  441.             while( ! end_of_line ){
  442.                 colour=get_colour(infile,img);
  443.                 if (!quiet && !end_of_line) fprintf(stderr,"), (");
  444.                 style[i++] = colour;
  445.             }
  446.             if (!quiet) fprintf(stderr,")\n");
  447.             gdImageSetStyle(img, style, i-1);
  448.             style_on = TRUE;
  449.             end_of_line = FALSE;
  450.             break;
  451.  
  452.         case KILLSTYLE:
  453.             style_on = 0;
  454.             if (!quiet) fprintf(stderr,"## Style Killed ##\n");
  455.             break;
  456.  
  457.         case SETTILE:
  458.             s = get_string(infile);
  459.             tilefile = fopen(s,"rb");
  460.             tile = gdImageCreateFromGif(tilefile);
  461.             gdImageSetTile(img,tile);
  462.             tile_on = TRUE;
  463.             if (!quiet) fprintf(stderr,"## Tile Set ## to: %s\n",s);
  464.             break;
  465.  
  466.         case KILLTILE:
  467.             tile_on = 0;
  468.             if (!quiet) fprintf(stderr,"## Tile Killed ##\n");
  469.             break;
  470.  
  471.         case COPY:
  472.             copy_to_gif(infile, img, 0);
  473.             break;
  474.  
  475.         case COPYRESIZED:
  476.             copy_to_gif(infile, img, 1);
  477.             break;
  478.  
  479.         case TRANSPARENT:
  480.             if (!quiet) fprintf(stderr,"## Make transparent [");
  481.             colour=get_colour(infile,img);
  482.             gdImageColorTransparent(img,colour);
  483.             if (!quiet) fprintf(stderr,"]\n");
  484.             break;
  485.  
  486.         case INTERLACE:
  487.             gdImageInterlace(img,1);
  488.             if (!quiet) fprintf(stderr,"Image is interlaced\n");
  489.             break;
  490.  
  491.         case SIZEX:
  492.             size = gdImageSX(img);
  493.             if (!quiet) fprintf(stderr,"## Size - X ## is %d\n",size);
  494.             break;
  495.  
  496.         case SIZEY:
  497.             size = gdImageSY(img);
  498.             if (!quiet) fprintf(stderr,"## Size - Y ## is %d\n",size);
  499.             break;
  500.  
  501.         case COMMENT:
  502.             sync_input(infile);
  503.             break;
  504.  
  505.         default:
  506.             if( ! finished )
  507.             {
  508.                 if (!quiet)
  509.                     fprintf(stderr,"Line Skipped, bad directive or syntax error\n");
  510.             }
  511.             else
  512.             {
  513.                 if (!quiet) fprintf(stderr,"EOF: fly finished.\n");
  514.             }
  515.             sync_input(infile);
  516.             break;
  517.         }
  518.     }    while( ! finished );
  519.  
  520.     /*  Write the gd to the GIF output file and exit */
  521.     gdImageGif(img,outfile);
  522.     fclose(outfile);
  523.     gdImageDestroy(img);
  524.     exit(0);
  525. }
  526.  
  527. /******************************************************************************
  528. **
  529. **  get_string
  530. **
  531. **  returns a string from the current input line: from the current point
  532. **  to the end of line.
  533. **
  534. **  Used by:
  535. **  string,stringup,chr,chrup,setbrush,settile
  536. **
  537. ******************************************************************************/
  538. char *get_string(FILE *infile){
  539.     int     c,i=0;
  540.     char    temp[1024], *string, *p;
  541.  
  542.     while(( (c=getc(infile)) != EOF ) && ( c != '\n') ){
  543.         temp[i++]=c;
  544.     }
  545.  
  546.     if( c == EOF ) {
  547.         finished = TRUE;
  548.     }
  549.     temp[i]='\0';
  550.     p=temp;
  551.     string=(char *)my_newmem(strlen(p));
  552.     sprintf(string,"%s",temp);
  553.  
  554.     return string;
  555. }
  556.  
  557. /******************************************************************************
  558. **
  559. **  get_token
  560. **
  561. **  Gets the next "token" from the input line.
  562. **
  563. **  Used by:
  564. **  all
  565. **
  566. ******************************************************************************/
  567. int get_token(FILE *infile){
  568.     int     c,i=0;
  569.     char    temp[80], *input_type, *p;
  570.     char    *line="line", *poly="poly", *fpoly="fpoly", *rect="rect",
  571.             *frect="frect", *dline="dline", *arc="arc", *size="size",
  572.             *new="new", *existing="existing", *setpixel="setpixel",
  573.             *filltoborder="filltoborder", *fill="fill", *string="string",
  574.             *stringup="stringup", *copy="copy", *copyresized="copyresized",
  575.             *transparent="transparent", *interlace="interlace", *sizex="sizex",
  576.             *sizey="sizey", *setbrush="setbrush", *killbrush="killbrush",
  577.             *settile="settile", *killtile="killtile", *setstyle="setstyle",
  578.             *killstyle="killstyle", *tiny="tiny", *small="small",
  579.             *medium="medium", *large="large", *giant="giant",
  580.             *zero="0", *one="1", *circle="circle", *comment="#";
  581.  
  582.     while(((c=getc(infile))!=EOF)&&(c!=' ')&&(c!='\n')&&(c!=',')&&(c!='='))
  583.     {
  584.         temp[i++]=c;
  585.         if(temp[0] == '#') break;
  586.     }
  587.  
  588.     if( c == EOF )
  589.     {
  590.         finished = TRUE;
  591.         return NULL;
  592.     }
  593.     temp[i]='\0';
  594.     p=temp;
  595.     input_type=(char*)my_newmem(strlen(p));
  596.     sprintf(input_type,"%s",temp);
  597.  
  598.     if( strcmp(input_type, line) == 0 ){
  599.         free(input_type);
  600.         return LINE;
  601.     }
  602.     if( strcmp(input_type, rect) == 0 ){
  603.         free(input_type);
  604.         return RECT;
  605.     }
  606.     if( strcmp(input_type, dline) == 0 ){
  607.         free(input_type);
  608.         return DLINE;
  609.     }
  610.     if( strcmp(input_type, frect) == 0 ){
  611.         free(input_type);
  612.         return FRECT;
  613.     }
  614.     if( strcmp(input_type, circle) == 0 ){
  615.         free(input_type);
  616.         return CIRCLE;
  617.     }
  618.     if( strcmp(input_type, arc) == 0 ){
  619.         free(input_type);
  620.         return ARC;
  621.     }
  622.     if( strcmp(input_type, poly) == 0 ){
  623.         free(input_type);
  624.         return POLY;
  625.     }
  626.     if( strcmp(input_type, fpoly) == 0 ){
  627.         free(input_type);
  628.         return FPOLY;
  629.     }
  630.     if( strcmp(input_type, size) == 0 ){
  631.         free(input_type);
  632.         return SIZE;
  633.     }
  634.     if( strcmp(input_type, new) == 0 ){
  635.         free(input_type);
  636.         return NEW;
  637.     }
  638.     if( strcmp(input_type, existing) == 0 ){
  639.         free(input_type);
  640.         return EXISTING;
  641.     }
  642.     if( strcmp(input_type, copyresized) == 0 ){
  643.         free(input_type);
  644.         return COPYRESIZED;
  645.     }
  646.     if( strcmp(input_type, copy) == 0 ){
  647.         free(input_type);
  648.         return COPY;
  649.     }
  650.     if( strcmp(input_type, fill) == 0 ){
  651.         free(input_type);
  652.         return FILL;
  653.     }
  654.     if( strcmp(input_type, filltoborder) == 0 ){
  655.         free(input_type);
  656.         return FILLTOBORDER;
  657.     }
  658.     if( strcmp(input_type, setpixel) == 0 ){
  659.         free(input_type);
  660.         return SETPIXEL;
  661.     }
  662.     if( strcmp(input_type, string) == 0 ){
  663.         free(input_type);
  664.         return STRING;
  665.     }
  666.     if( strcmp(input_type, stringup) == 0 ){
  667.         free(input_type);
  668.         return STRINGUP;
  669.     }
  670.     if( strcmp(input_type, sizex) == 0 ){
  671.         free(input_type);
  672.         return SIZEX;
  673.     }
  674.     if( strcmp(input_type, sizey) == 0 ){
  675.         free(input_type);
  676.         return SIZEY;
  677.     }
  678.     if( strcmp(input_type, setbrush) == 0 ){
  679.         free(input_type);
  680.         return SETBRUSH;
  681.     }
  682.     if( strcmp(input_type, killbrush) == 0 ){
  683.         free(input_type);
  684.         return KILLBRUSH;
  685.     }
  686.     if( strcmp(input_type, settile) == 0 ){
  687.         free(input_type);
  688.         return SETTILE;
  689.     }
  690.     if( strcmp(input_type, killtile) == 0 ){
  691.         free(input_type);
  692.         return KILLTILE;
  693.     }
  694.     if( strcmp(input_type, setstyle) == 0 ){
  695.         free(input_type);
  696.         return SETSTYLE;
  697.     }
  698.     if( strcmp(input_type, killstyle) == 0 ){
  699.         free(input_type);
  700.         return KILLSTYLE;
  701.     }
  702.     if( strcmp(input_type, interlace) == 0 ){
  703.         free(input_type);
  704.         return INTERLACE;
  705.     }
  706.     if( strcmp(input_type, transparent) == 0 ){
  707.         free(input_type);
  708.         return TRANSPARENT;
  709.     }
  710.     if( strcmp(input_type, tiny) == 0 ){
  711.         free(input_type);
  712.         return TINY;
  713.     }
  714.     if( strcmp(input_type, zero) == 0 ){
  715.         free(input_type);
  716.         return SMALL;
  717.     }
  718.     if( strcmp(input_type, small) == 0 ){
  719.         free(input_type);
  720.         return SMALL;
  721.     }
  722.     if( strcmp(input_type, medium) == 0 ){
  723.         free(input_type);
  724.         return MEDIUM;
  725.     }
  726.     if( strcmp(input_type, one) == 0 ){
  727.         free(input_type);
  728.         return LARGE;
  729.     }
  730.     if( strcmp(input_type, large) == 0 ){
  731.         free(input_type);
  732.         return LARGE;
  733.     }
  734.     if( strcmp(input_type, giant) == 0 ){
  735.         free(input_type);
  736.         return GIANT;
  737.     }
  738.     if( strcmp(input_type, comment) == 0){
  739.         free(input_type);
  740.         return COMMENT;
  741.     }
  742.     free(input_type);
  743.     return NULL;
  744. }
  745.  
  746. /******************************************************************************
  747. **
  748. **  get_number
  749. **
  750. **  grabs a number from the current input line. Reads up to a comma or newline.
  751. **
  752. **  Used by:
  753. **  line, dline, rect, frect, poly, fpoly, arc, setpixel, fill, filltoborder,
  754. **  string, stringup, chr, chrup.
  755. **
  756. ******************************************************************************/
  757. int get_number(FILE *infile){
  758.     int     c,i=0;
  759.     char    tmp[80];
  760.  
  761.     while(( (c=getc(infile)) != EOF ) && ( c != ',') && (c != '\n')){
  762.         tmp[i++]=c;
  763.     }
  764.     if( c != EOF ) {
  765.         tmp[i]='\0';
  766.         if( c == '\n') {
  767.             done = TRUE;
  768.         }
  769.         return atoi(tmp);
  770.     }
  771.     else {
  772.         tmp[i]='\0';
  773.         finished = TRUE;
  774.         return atoi(tmp);
  775.     }
  776.     return NULL;
  777. }
  778.  
  779. /******************************************************************************
  780. **
  781. **  get_colour
  782. **
  783. **  Gets a R,G,B colour value from the current input line.
  784. **  Returns the integer colour index.
  785. **
  786. **  Used by:
  787. **  line, dline, rect, frect, poly, fpoly, arc, setpixel, fill, filltoborder,
  788. **  string, stringup, chr, chrup, setstyle, transparent.
  789. **
  790. ******************************************************************************/
  791. int get_colour(FILE *infile, gdImagePtr img){
  792.     int     c,i,count,colourIndex, colour[3];
  793.     char    temp[5];
  794.  
  795.     for(count=0;count<3;count++){
  796.         i=0;
  797.         while(( (c=getc(infile)) != EOF )&&( c !=',')&&(c !='\n')){
  798.             temp[i++]=c;
  799.         }
  800.         temp[i]='\0';
  801.         if( c == '\n') end_of_line = TRUE;
  802.         if( c == EOF ) finished = TRUE;
  803.         colour[count]=atoi(temp);
  804.     }
  805.     if( (c=getc(infile)) != EOF )  { 
  806.         ungetc(c,infile); 
  807.     }
  808.     else { 
  809.         finished = TRUE; 
  810.     }
  811.     /* Original comments from Claus Hofmann. I don't have any idea what they
  812.          * mean, but I'll put 'em here anyhow.
  813.      */
  814.     /* zuerst nachschauen, ob es die gewuenschte Farbe schon in der 
  815.      * colortable gibt. Erst wenn es die Farbe nicht gibt einen neuen
  816.      * Index in der Tabelle allocieren.
  817.      */
  818.     colourIndex=gdImageColorExact(img,colour[0],colour[1],colour[2]);
  819.     if (-1 == colourIndex) {
  820.         colourIndex=gdImageColorAllocate(img,colour[0],colour[1],colour[2]);
  821.     }
  822.     if (!quiet)
  823.         fprintf(stderr,"colour: %d, %d, %d = %d",
  824.             colour[0],colour[1],colour[2], colourIndex);
  825.     return colourIndex;
  826.  
  827. }
  828.  
  829. /******************************************************************************
  830. **
  831. **  copy_to_gif
  832. **
  833. **  Copies a gif to the current image. Location of gif and coordinates are
  834. **  specified on the input line.
  835. **
  836. **  Used by:
  837. **  copy, copyresized.
  838. **
  839. ******************************************************************************/
  840. void copy_to_gif(FILE *infile, gdImagePtr img, int resize){
  841.     int     c,i=0,arg[8];
  842.     char    temp[1256], *filename;
  843.     FILE    *img_to_copy;
  844.     gdImagePtr    img_file;
  845.  
  846.     /*    Get the coordinates    */
  847.     for(i=0;i<=5;i++){
  848.         arg[i]=get_number(infile);
  849.     }
  850.     if( resize == 1 ){
  851.         arg[i]=get_number(infile);
  852.         i++;
  853.         arg[i]=get_number(infile);
  854.     }
  855.     i=0;
  856.     /*    Get the filename    */
  857.     while(( (c=getc(infile)) != EOF ) && ( c != ' ') && ( c != '\n') ){
  858.         temp[i++]=c;
  859.     }
  860.     temp[i]='\0';
  861.     filename=(char*)my_newmem(i * sizeof(char));
  862.     sprintf(filename,"%s",temp);
  863.     
  864.     if(!quiet) fprintf(stderr,"Copying GIF from existing file: %s\n",filename);
  865.  
  866.     if( (img_to_copy = fopen(filename, "rb")) == NULL ) {
  867.         fprintf(stderr,"Error: Cannot read existing GIF file \"%s\"\n",
  868.             filename);
  869.         exit(0);
  870.     }
  871.     img_file = gdImageCreateFromGif(img_to_copy);
  872.     fclose(img_to_copy);
  873.  
  874.     if ((arg[2] == -1)&&(arg[3] == -1) &(arg[4] == -1)&&(arg[5] == -1)) {
  875.             /* another comment from Claus Hofmann. I'm getting curious now. */
  876.             /* gesamtes Bild 
  877.             */
  878.         arg[2] = arg[3] = 0;
  879.         arg[4] = img_file->sx;
  880.         arg[5] = img_file->sy;
  881.     }
  882.     if( resize == 1 )
  883.     {
  884.         if(!quiet) fprintf(stderr,"Copying %s (area %d,%d - %d,%d) to area %d,%d - %d,%d.\n",
  885.             filename,arg[4],arg[5],arg[6], arg[7],arg[0],arg[1],arg[2],arg[3]);
  886.         gdImageCopyResized(img, img_file, arg[4], arg[5], arg[0], arg[1],
  887.             (arg[6] - arg[4]), (arg[7] - arg[5]), (arg[2] - arg[0]),
  888.             (arg[3] - arg[1]));
  889.     }
  890.     else
  891.     {
  892.         if(!quiet) fprintf(stderr,"Copying %s to coordinates %d,%d\n",filename,arg[0],arg[1]);
  893.         gdImageCopy(img, img_file, arg[0], arg[1], arg[2], arg[3],
  894.                     arg[4] - arg[2], arg[5] - arg[3]);
  895.     }
  896.     gdImageDestroy(img_file);
  897.  
  898.     return;
  899. }
  900.  
  901. /******************************************************************************
  902. **
  903. **  sync_input
  904. **
  905. **  synchronises input line - reads to end of line, leaving file pointer
  906. **  at first character of next line.
  907. **
  908. **  Used by:
  909. **  main program - error handling.
  910. **
  911. ******************************************************************************/
  912. void
  913. sync_input(FILE *infile)
  914. {
  915.     int c;
  916.  
  917.     while( ( (c=getc(infile)) != EOF ) && (c != '\n') ) ;
  918.     if( c == EOF ) finished = TRUE;
  919.     return;
  920. }
  921.  
  922. /******************************************************************************
  923. **
  924. **  process_args
  925. **
  926. **  processes the command line arguments
  927. **
  928. **  Used by:
  929. **  main program.
  930. **
  931. ******************************************************************************/
  932. int
  933. process_args(int argc, char *argv[])
  934. {
  935.     char *check;
  936.     int c, errflag=0;
  937.     extern char *optarg;
  938.     extern int optind;
  939.  
  940.     /* if( (check=strstr(argv[0],"flycgi")) != NULL ) 
  941.     {
  942.         quiet = TRUE;
  943.         fprintf(stdout,"Content-type: image/gif\n\n");
  944.     } */
  945.  
  946.     while ((c=getopt(argc, argv, "qhvi:o:")) != EOF)
  947.     {
  948.         switch (c) {
  949.             case 'q': quiet = TRUE;
  950.                     break;
  951.             case 'v':
  952.             case 'h': fprintf(stderr,"fly, version %s\n\n%s\n", version, help);
  953.                       exit(0);
  954.                     break;
  955.             case 'o': output_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
  956.                       sprintf(output_file,"%s",optarg);
  957.                     break;
  958.             case 'i': input_file=(char *)my_newmem(strlen(optarg)*sizeof(char));
  959.                       sprintf(input_file,"%s",optarg);
  960.                     break;
  961.             case '?': errflag = 1;
  962.                     break;
  963.         }
  964.         if (errflag)
  965.         {
  966.             fprintf(stderr,"%s\n", usage);
  967.             exit(1);
  968.         }
  969.     }
  970.     if( input_file )
  971.     {
  972.         if ( (infile = fopen(input_file,"r")) == NULL )
  973.         {
  974.             fprintf(stderr, "Failed to open input file, %s.\n",
  975.                 input_file);
  976.             return FALSE;
  977.         }
  978.     }
  979.     else
  980.     {
  981.         infile = stdin;
  982.     }
  983.     if( output_file )
  984.     {
  985.         if ( (outfile = fopen(output_file,"wb")) == NULL )
  986.         {
  987.             fprintf(stderr, "Failed to open output file, %s.\n",
  988.                 output_file);
  989.             return FALSE;
  990.         }
  991.     }
  992.     else
  993.     {
  994.         outfile = stdout;
  995.     }
  996.     return TRUE;
  997. }
  998.  
  999. /******************************************************************************
  1000. **
  1001. **  get_image
  1002. **
  1003. **  creates a new image or uses an existing one as a template.
  1004. **
  1005. **  Used by:
  1006. **  main program
  1007. **
  1008. ******************************************************************************/
  1009. gdImagePtr get_image(int type, int argc, char *argv[]){
  1010.     FILE *in;
  1011.     int n=0, ch, num[10];
  1012.     char fname[1256], *filename;
  1013.     gdImagePtr image;
  1014.     int newtype;
  1015.  
  1016.     if( type == EXISTING ) {
  1017.         /*     fprintf(stderr,"Creating GIF from existing file:"); */
  1018.         while(( (ch=getc(infile)) != EOF ) && ( ch != ' ') && ( ch != '\n')){
  1019.             fname[n++]=ch;
  1020.         }
  1021.         fname[n]='\0';
  1022.         filename = (char *) my_newmem( n );
  1023.         sprintf(filename,"%s",fname);
  1024.         /*  fprintf(stderr," %s\n",filename); */
  1025.         if( (in = fopen(filename, "rb")) == NULL ) {
  1026.             fprintf(stderr,"Error: Cannot read existing GIF file \"%s\"\n",
  1027.                 filename);
  1028.             exit(0);
  1029.         }
  1030.         else {
  1031.             if(!quiet) fprintf(stderr,"Creating image from existing gif <%s>\n",
  1032.                 filename);
  1033.             image = gdImageCreateFromGif(in);
  1034.             fclose(in);
  1035.         }
  1036.     }
  1037.     else if( type == NEW ){
  1038.         newtype = get_token(infile);
  1039.         while( (newtype == COMMENT) || (newtype != SIZE) )
  1040.         {
  1041.             sync_input(infile);
  1042.             newtype = get_token(infile);
  1043.         }
  1044.         if( newtype != SIZE ) {
  1045.             if( argc == 2){
  1046.                 fprintf(stderr,"Error: <stdin> second line ");
  1047.                 fprintf(stderr,"must have a 'size' command\n");
  1048.             }
  1049.             else{
  1050.                 fprintf(stderr,"Error: %s second line must ");
  1051.                 fprintf(stderr,"have a 'size' command\n",argv[1]);
  1052.             }
  1053.             exit(0);
  1054.         }
  1055.         for( n=1; n<=2; n++ ){
  1056.             num[n]=get_number(infile);
  1057.         }
  1058.         if (!quiet) fprintf(stderr,"Creating new %d by %d gif, <%s>\n",
  1059.                 num[1],num[2],output_file);
  1060.         image = gdImageCreate(num[1],num[2]);
  1061.     }
  1062.     return image;
  1063. }
  1064.  
  1065. /******************************************************************************
  1066. **
  1067. **  my_newmem: grab some memory.
  1068. **
  1069. **  -  Concentrates memory error handling in one place.
  1070. **
  1071. **
  1072. **  Used by:
  1073. **  string,stringup,chr,chrup,setbrush,settile
  1074. **
  1075. ******************************************************************************/
  1076. void *
  1077. my_newmem(size_t size)
  1078. {
  1079.     void    *p;
  1080.  
  1081.     if ((p = malloc(size +1)) == NULL)
  1082.     {
  1083.         fprintf(stderr, "fly: ran out of memory\n");
  1084.         exit(1);
  1085.     }
  1086.  
  1087.     return p;
  1088. }
  1089.  
  1090. /******************************************************************************/
  1091.